﻿#region Header

/*
Behavioral Rating of Dancing Human Crowds based on Motion Patterns
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.Linq;
using paravili.Services;
using Sebarf.Services.Interfaces;

#endregion

namespace paravili.Steps {
	/// <summary>
	/// calculates the moving average of the stored statistiv value with the id StatisticValueField of the StatisticValuesLocatorService
	/// stores the calculated value by the StatisticValuesLocatorService with the id StatisticValueOutputField
	/// </summary>
	public class CalculateMovingAverageOfStatisticValue : ProcessStepWithMeasurement<Object> {
		#region Public Properties

		[ServiceRequest]
		public IStatisticValuesLocatorService StatisticValuesLocatorService { get; set; }

		[ConfigurabelBooleanValue(Name = "is enable")]
		public bool IsEnable { get; set; }

		[ConfigurabelStringValue(Name = "StatisticValue to observer")]
		public string StatisticValueField { get; set; }

		[ConfigurabelStringValue(Name = "StatisticValue for the result")]
		public string StatisticValueOutputField { get; set; }

		[ConfigurableNumericValue(Name = "numbers measures are used for the average", RangeFrom = 1, RangeTo = 20)]
		public int NumbersOfMeasureForTheAverage { get; set; }

		[ServiceRequest]
		public IResetHandlerService ResetHandlerService {
			set { value.Reset += OnReset; }
		}

		#endregion

		#region Public Methods

		public CalculateMovingAverageOfStatisticValue() {
			StatisticValueField = "Movement@Other";
			StatisticValueOutputField = "Movement@Other.Average";
			IsEnable = true;
			NumbersOfMeasureForTheAverage = 10;
		}

		#endregion

		#region Private Methods

		private void OnReset(object sender, EventArgs e) {
			m_values.Clear();
		}

		#endregion

		#region Private Fields

		private readonly Queue<int> m_values = new Queue<int>();

		#endregion

		protected override object OnProcess(object toProcess) {
			if (!IsEnable) {
				return toProcess;
			}
			StatisticValueEntry staticValue = StatisticValuesLocatorService[StatisticValueField];
			if (staticValue != null) {
				object v = staticValue.Value;
				if (v is int) {
					var intValue = (int)v;
					if (m_values.Count > NumbersOfMeasureForTheAverage) {
						m_values.Dequeue();
					}
					m_values.Enqueue(intValue);
					StatisticValuesProviderService.SetStatisticValue(StatisticValueOutputField,
																	  (int)(m_values.Sum(x => x) / (double)m_values.Count));
				}
			}
			return toProcess;
		}
	}
}